package com.xpxrule.util;

import com.googlecode.aviator.AviatorEvaluator;
import com.xpxrule.AviatorExecuteUtil;
import com.xpxrule.constant.FieldType;
import com.xpxrule.constant.Operator;
import com.xpxrule.constant.ValueType;
import com.xpxrule.dataobject.base.StructValue;
import com.xpxrule.dataobject.bo.RuleConditionItemBo;
import com.xpxrule.dataobject.vo.RuleVo;
import com.xpxrule.strategy.FieldTypeStrategyContext;
import com.xpxrule.strategy.field.FieldTypeStrategy;
import com.xpxrule.strategy.operator.OperatorStrategy;
import com.xpxrule.strategy.OperatorStrategyContext;

import java.util.*;
import java.util.stream.Collectors;

public class AviatorFieldUtil {
    public static String translateAviatorSyntax(List<RuleConditionItemBo> conditionItemList, Map<String, Object> targetParams) throws Exception {
        /**
         * 根据字段取值类型转为字符串
         * 类型包括：数值类型、金额类型、时间类型
         */
        List<String> fieldStrList = new ArrayList<>();
        for (RuleConditionItemBo conditionItem : conditionItemList) {
            String aviatorStringItem = getAviatorStringFromRuleConditionItem(conditionItem, targetParams);
            fieldStrList.add(aviatorStringItem);
        }
        /**
         * 翻译aviator语句流程
         * 2处策略模式
         *  1：operator策略模式
         *  2：fieldType策略模式
         * 流程如下：
         * 1：根据operator获取特定策略：此处获取信息，取值类型（单值、范围值、集合值）
         * 2: 根据取值类型执行该operator策略执行对应执行策略
         * 3：根据字段类型获取特定策略：此处获取信息，
         */
        return String.join(" && ", fieldStrList);
    }

    /**
     * 将每个字段对应的规则翻译为对应aviator语句
     *
     * @param conditionItem
     * @param params
     * @return
     */
    private static String getAviatorStringFromRuleConditionItem(RuleConditionItemBo conditionItem, Map<String, Object> params) throws Exception {
        String aviatorStr = null;
        Operator operator = conditionItem.getOperator();
        OperatorStrategy operatorStrategy = OperatorStrategyContext.getOperatorStrategy(operator);
        aviatorStr = operatorStrategy.getAviatorExpression(conditionItem, params);
        return aviatorStr;
    }

    /**
     * 将参数中对应字段转换为对应类型的字符串
     * @param params
     * @param fieldTypeMap
     * @return
     */
    public static Map<String, Object> translateParamsField(Map<String, Object> params, Map<String, FieldType> fieldTypeMap, List<RuleConditionItemBo> conditionItemBoList) {
        Map<String, Object> fieldStrMap = AviatorEvaluator.newEnv();
        for (Map.Entry<String, FieldType> entry : fieldTypeMap.entrySet()) {
            String fieldKey = entry.getKey();
            Object fieldObject = null;
            FieldType fieldType = entry.getValue();
            FieldTypeStrategy fieldTypeStrategy = FieldTypeStrategyContext.getFieldTypeStrategy(fieldType);
            fieldObject = fieldTypeStrategy.getEnvFieldParamObject(params.get(fieldKey));
            fieldStrMap.put(fieldKey, fieldObject);
        }
        for (RuleConditionItemBo conditionItemBo : conditionItemBoList) {
            FieldType fieldType = conditionItemBo.getFieldBasicType();
            FieldTypeStrategy fieldTypeStrategy = FieldTypeStrategyContext.getFieldTypeStrategy(fieldType);
            StructValue targetValue = conditionItemBo.getTargetValue();
            // 集合值
            if (targetValue.getValueType() == ValueType.COLLECTION) {
                List list = targetValue.getList();
                List fieldCollection = fieldTypeStrategy.getEnvFieldCollection(list);
                fieldStrMap.put(String.format(AviatorExecuteUtil.AVIATOR_PREFIX_FORMAT, AviatorExecuteUtil.AVIATOR_RIGHT_PREFIX, conditionItemBo.getFieldKey()), fieldCollection);
            }
//            // 单值
//            if (targetValue.getValueType() == ValueType.SINGLE) {
//                Object single = targetValue.getSingle();
//                Object paramObject = fieldTypeStrategy.getEnvFieldParamObject(single);
//                fieldStrMap.put(String.format(AviatorExecuteUtil.AVIATOR_PREFIX_FORMAT, AviatorExecuteUtil.AVIATOR_RIGHT_PREFIX, conditionItemBo.getFieldKey()), paramObject);
//            }
        }
        return fieldStrMap;
    }

    /**
     * 获取字段对应字段类型
     * @param ruleVo
     * @return
     */
    public static Map<String, FieldType> getFieldTypeMap(RuleVo ruleVo) {
        List<RuleConditionItemBo> conditionDetail = ruleVo.getConditionDetail();
        return conditionDetail
                .stream()
                .collect(Collectors.toMap(RuleConditionItemBo::getFieldKey, RuleConditionItemBo::getFieldBasicType));
    }
}
